package ws

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
	"strings"
	"sync"
)

type Websocket struct {
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有跨域请求，实际使用时请根据需要修改
	},
}

// Room 聊天室
type Room struct {
	ID        string
	Clients   map[*Client]bool
	Broadcast chan []byte
	Destroy   chan struct{}
	mu        sync.Mutex
}

// Client 一个连接到房间的客户端
type Client struct {
	Conn     *websocket.Conn
	Room     *Room
	Username string
}

// Message 聊天消息（后续启用）
type Message struct {
	Type     string `json:"type"` // "message", "join", "leave"
	Username string `json:"username"`
	Content  string `json:"content"`
	RoomID   string `json:"roomId"`
}

// Server 管理所有房间和客户端
type Server struct {
	Rooms map[string]*Room
	mu    sync.RWMutex
}

var server = &Server{
	Rooms: make(map[string]*Room),
}

func (Websocket) WebsocketHandler(c *gin.Context) {
	roomId := strings.TrimSpace(c.Query("roomId"))
	username := strings.TrimSpace(c.Query("username"))
	if roomId == "" {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "请输入房间号"})
		return
	}
	//是否存在房间号，不存在则创建
	room, ok := server.Rooms[roomId]
	if !ok {
		room = createRoom(roomId)
	}

	// 升级HTTP请求为WebSocket连接
	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		fmt.Println("Failed to upgrade connection:", err)
		return
	}

	if username == "" {
		username = ws.NetConn().RemoteAddr().String()
	}
	client := &Client{
		Room:     room,
		Username: username,
		Conn:     ws,
	}
	room.mu.Lock()
	room.Clients[client] = true
	room.mu.Unlock()
	go client.read()
	msg := Message{
		Type:     "system",
		Username: "system",
		Content:  fmt.Sprintf("欢迎【%s】加入房间【%s】\n", username, roomId),
		RoomID:   roomId,
	}
	message, _ := json.Marshal(msg)
	room.Broadcast <- message
}

// createRoom 创建新房间
func createRoom(roomId string) *Room {
	room := &Room{
		ID:        roomId,
		Broadcast: make(chan []byte),
		Clients:   make(map[*Client]bool),
		Destroy:   make(chan struct{}),
	}
	server.mu.Lock()
	server.Rooms[roomId] = room
	server.mu.Unlock()
	go room.run()
	return room
}

// run 运行房间
func (r *Room) run() {
	fmt.Printf("房间【%s】已就绪\n", r.ID)
	defer func() {
		fmt.Printf("房间【%s】已销毁\n", r.ID)
		close(r.Broadcast)
		close(r.Destroy)
		server.mu.Lock()
		delete(server.Rooms, r.ID)
		server.mu.Unlock()
	}()
	for {
		select {
		case msg := <-r.Broadcast:
			for client, ok := range r.Clients {
				if ok {
					if err := client.Conn.WriteMessage(websocket.TextMessage, msg); err != nil {
						delete(r.Clients, client)
						client.Conn.Close()
					}
				}
			}
		case <-r.Destroy:
			return
		}
	}
}

// 从客户端读取信息
func (c *Client) read() {
	defer func() {
		fmt.Printf("房间【%s】中的【%s】断开连接\n", c.Room.ID, c.Username)
		c.Room.mu.Lock()
		delete(c.Room.Clients, c)
		c.Room.mu.Unlock()
		c.Conn.Close()
		if len(c.Room.Clients) == 0 {
			c.Room.Destroy <- struct{}{}
		}
	}()
	for {
		_, msg, err := c.Conn.ReadMessage()
		if err != nil {
			if websocket.IsCloseError(err,
				websocket.CloseNormalClosure,
				websocket.CloseGoingAway,
				websocket.CloseAbnormalClosure,
				websocket.CloseNoStatusReceived,
			) {
				break
			}
		}
		//把读到的信息在同房间里面广播
		c.Room.Broadcast <- msg
	}
}
